import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class MyCollector {
    public static void main(String[] args) {
        // 1.创建新的结果容器
        Supplier<IntegerSum> supplier = IntegerSum::new;
        // 2.将元素添加到结果容器
        BiConsumer<IntegerSum, Integer> accumulator = IntegerSum::doSum;
        // 3.合并多个结果容器
        BinaryOperator<IntegerSum> combiner = IntegerSum::doCombine;
        // 4.最终结果的转换
        Function<IntegerSum, Integer> finisher = IntegerSum::toValue;
        /**
         * 泛型说明
         * T 待收集元素的类型
         * A 累加器的类型
         * R 最终结果的类型
         */
        Collector<Integer, IntegerSum, Integer> collector = new Collector<Integer, IntegerSum, Integer>() {
            @Override
            public Supplier<IntegerSum> supplier() {
                return IntegerSum::new;
            }

            @Override
            public BiConsumer<IntegerSum, Integer> accumulator() {
                return IntegerSum::doSum;
            }

            @Override
            public BinaryOperator<IntegerSum> combiner() {
                return IntegerSum::doCombine;
            }

            @Override
            public Function<IntegerSum, Integer> finisher() {
                return IntegerSum::toValue;
            }

            @Override
            public Set<Characteristics> characteristics() {
                return Collections.emptySet();
            }
        };
        Integer result = Stream.of(1, 3, 5, 7).collect(collector);
        System.out.println("result = " + result);
    }
}

class IntegerSum {
    int sum;

    public IntegerSum doSum(Integer item) {
        if (item % 2 == 0) {
            this.sum += item * 2;
        } else {
            this.sum += item;
        }
        return this;

    }

    public IntegerSum doCombine(IntegerSum it) {
        this.sum += it.sum;
        return this;
    }

    public Integer toValue() {
        return this.sum;
    }

}
